﻿using System;
using System.Collections.Generic;
using System.Text;
using Kugar.Core.Exceptions;

namespace Kugar.Core.Communications.Transfer
{
    public class RUDPFactory : TransferFactoryBase
    {
        private Dictionary<int, RUDPServer> _cacheRUDPServer = new Dictionary<int, RUDPServer>(3);
        private object lockerObj = new object();

        public override void Listen(TransferConnectConfig config)
        {
            if (!(config is RUDPConnectConfig))
            {
                throw new ArgumentException("RUDP连接的创建,请传入RUDPConnectConfig类型的配置类", "config");
            }

            var rudpConfig = (RUDPConnectConfig)config;


            RUDPServer rudpServer = getRUDPServer(rudpConfig.LocalPort);

            if (rudpServer != null)
            {
                rudpServer.Listen();
            }

            //if (!_cacheRUDPServer.TryGetValue(rudpConfig.LocalPort, out rudpServer))
            //{
            //    rudpServer = new RUDPServer(rudpConfig.LocalPort);
            //    rudpServer.Listen();
            //}
            //else
            //{
            //    rudpServer.Listen();
            //}

        }

        public override void StopListen(TransferConnectConfig port)
        {
            if (!(port is RUDPConnectConfig))
            {
                throw new ArgumentTypeNotMatchException("port", "RUDPConnectConfig");
            }

            var rudp = (RUDPConnectConfig)port;

            RUDPServer rudpServer = getRUDPServer(rudp.LocalPort, false);

            if (rudpServer != null)
            {
                rudpServer.StopListen();
            }
        }

        public override void ClosePort(TransferConnectConfig port)
        {
            if (!(port is RUDPConnectConfig))
            {
                throw new ArgumentTypeNotMatchException("port", "RUDPConnectConfig");
            }

            var rudp = (RUDPConnectConfig)port;

            var rudpServer = getRUDPServer(rudp.LocalPort, false);

            rudpServer.Close();

            _cacheRUDPServer.Remove(rudp.LocalPort);
        }

        public override bool ConnectToAsync(TransferAsyncEventArgs ea, TransferConnectConfig config)
        {
            Exception error = null;

            if (!(config is RUDPConnectConfig))
            {
                error=TransferExceptionHelper.GetTransferException(new ArgumentException("RUDP连接的创建,请传入RUDPConnectConfig类型的配置类", "config"));
            }

            var rudpConfig = (RUDPConnectConfig)config;

            var t = getRUDPServer(rudpConfig.LocalPort);


            return t.ConnectAsync(ea, rudpConfig.RemotePoint);
        }

        //public override ITransfer ConnectTo(TransferConnectConfig config, ref Exception error)
        //{
        //    if (!(config is RUDPConnectConfig))
        //    {
        //        throw new ArgumentException("RUDP连接的创建,请传入RUDPConnectConfig类型的配置类", "config");
        //    }

        //    var rudpConfig = (RUDPConnectConfig)config;

        //    var t = getRUDPServer(rudpConfig.LocalPort);

        //    return t.ConnectTo(rudpConfig.RemotePoint);
        //}

        //public override IAsyncResult BeginConnectTo(TransferConnectConfig config, AsyncCallback callback, object state)
        //{
        //    if (!(config is RUDPConnectConfig))
        //    {
        //        throw new ArgumentException("RUDP连接的创建,请传入RUDPConnectConfig类型的配置类", "config");
        //    }

        //    var rudpConfig = (RUDPConnectConfig)config;

        //    var t = getRUDPServer(rudpConfig.LocalPort);

        //    return t.BeginConnectTo(rudpConfig.RemotePoint, callback, state);
        //}

        //public override ITransfer EndConnectTo(IAsyncResult iar, ref Exception error)
        //{
        //    if (!(iar is RUDPConnectAsyncResult))
        //    {
        //        throw new ArgumentException("请传入正确的IAsyncResult参数", "iar");
        //    }

        //    var ar = (RUDPConnectAsyncResult)iar;

        //    return ar.Server.EndConnectTo(iar, ref error);
        //}

        public override void Close()
        {
            lock (lockerObj)
            {
                foreach (var rudpServer in _cacheRUDPServer)
                {
                    rudpServer.Value.Close();
                }

                _cacheRUDPServer.Clear();
            }


        }

        //public event EventHandler<RemoteRequestConnectEventArgs> ConnectRequest;
        //public event EventHandler<RemoteConenctSuccessEventArgs> ConnectSuccessed;

        private RUDPServer getRUDPServer(int localPort, bool autoBuild = true)
        {
            RUDPServer udpServer = null;

            lock (lockerObj)
            {
                if (!_cacheRUDPServer.TryGetValue(localPort, out udpServer))
                {
                    if (autoBuild)
                    {
                        udpServer = new RUDPServer(localPort);
                        _cacheRUDPServer.Add(localPort, udpServer);
                        udpServer.ConnectRequest += (s, e) =>
                                                       {
                                                           OnConnectRequest(e);
                                                       };
                        udpServer.ConnectSuccessed += (s, e) =>
                                                          {
                                                              OnConnectSuccessed(e);
                                                          };
                    }

                }

                if (udpServer != null || !autoBuild)
                {
                    return udpServer;
                }
                else
                {
                    throw new Exception("端口无效或已被占用");
                }

            }
        }
    }


}
